#include<iostream>
#include<mutex>
using namespace std;


//饿汉模式
class HungryClass
{
public:
    static HungryClass& GetInstance() //引用方式返回 
    {
        return inst;
    }
private:
    HungryClass()
    {}
    HungryClass(const HungryClass&) = delete;
    HungryClass& operator=(const HungryClass&) = delete;
private:
    static HungryClass inst;
};
//静态成员变量在类外初始化
HungryClass HungryClass::inst;


//懒汉模式-版本1
class SlackerModel
{
public:
    static volatile SlackerModel& GetInstance()
    {
        //双检查加锁
        if(inst == nullptr)
        {
            unique_lock<mutex> ul(mtx);
            if(inst == nullptr)
            {
                inst = new SlackerModel();
            }
        }
        return *inst;
    }
private:
    SlackerModel()
    {}
    SlackerModel(const SlackerModel&) = delete;
    SlackerModel& operator=(const SlackerModel&) = delete;
private:
    volatile static SlackerModel* inst;
    static mutex mtx;
};
volatile SlackerModel* SlackerModel::inst = nullptr;
mutex SlackerModel::mtx;


//懒汉模式-版本2 -基于静态局部变量的懒汉模式
class SlackerModel_localVaribale
{
public:
    static SlackerModel_localVaribale& GetInstance()
    {
        static SlackerModel_localVaribale inst;
        return inst;
    }
private:
    SlackerModel_localVaribale()
    {}
    SlackerModel_localVaribale(const SlackerModel_localVaribale&) = delete;
    SlackerModel_localVaribale& operator=(const SlackerModel_localVaribale&) = delete;
};


//懒汉模式-版本3-释放单例对象
class SlackerModel_Destroy
{
public:
    static SlackerModel_Destroy& GetInstance()
    {
        //双检查加锁
        if(inst == nullptr)
        {
            unique_lock<mutex> ul(mtx);
            if(inst == nullptr)
            {
                inst = new SlackerModel_Destroy();
                atexit(Destroy);
            }
        }
        return *inst;
    }
    //方式3：使用atexit函数，注册程序结束之后的回调函数 ==>可以在第一次调用全局函数创建单例对象的时候注册
    //方式2：定义一个清理函数,可以由外部调用
    static void Destroy()
    {
        //由于多线程可能都会调用该函数，所以要加锁
        if(inst)
        {
            unique_lock<mutex> ul(mtx);
            if(inst)
            {
                delete inst;
                inst = nullptr;
            }
        }
    }
    //方式1：定义一个内部类，在单例类当中定义一个静态内部类对象
    class Garbo
    {
    public:
        Garbo()
        {}
        ~Garbo()
        {
            if(inst)
            {
                delete inst;
                inst = nullptr;
            }
        }
    };
private:
    SlackerModel_Destroy()
    {}
    SlackerModel_Destroy(const SlackerModel_Destroy&) = delete;
    SlackerModel_Destroy& operator=(const SlackerModel_Destroy&) = delete;
private:
    static Garbo gb;
    static SlackerModel_Destroy* inst;
    static mutex mtx;
};
SlackerModel_Destroy* SlackerModel_Destroy::inst = nullptr;
mutex SlackerModel_Destroy::mtx;
SlackerModel_Destroy::Garbo gb;

int main()
{

    return 0;
}